package jinyilw.swing.rlaf.ui.icon;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.plaf.UIResource;

import jinyilw.swing.ComponentTools;
import jinyilw.swing.graphics.GraphicsTools;
import jinyilw.swing.graphics.RenderingConfig;
import jinyilw.swing.graphics.ShapeTools;
import jinyilw.swing.icon.LazyScaleIcon;
import jinyilw.swing.rlaf.UITools;
import jinyilw.swing.rlaf.theme.RColorSet;
import jinyilw.swing.rlaf.theme.RThemeColor;

public class RIconFactory
{
	private static final AlphaComposite alphaComposite = ComponentTools.alphaComposite;
	public static final Color borderColor = new Color(70, 70, 70, 220);
	private static Icon closeIcon, minIcon, maxIcon, iconIcon;
	private static Icon thumbIcon, thumbRolloverIcon;
	private static Icon radioIcon, checkIcon;

	private RIconFactory()
	{
	}

	public static Icon getCloseIcon()
	{
		if (closeIcon == null)
		{
			closeIcon = new CloseSymbol(Color.red.brighter());
		}
		return closeIcon;
	}

	public static Icon getMinIcon()
	{
		if (minIcon == null)
		{
			minIcon = new MinSymbol(Color.yellow);
		}
		return minIcon;
	}

	public static Icon getMaxIcon()
	{
		if (maxIcon == null)
		{
			maxIcon = new MaxSymbol(Color.yellow);
		}
		return maxIcon;
	}

	public static Icon getIconIcon()
	{
		if (iconIcon == null)
		{
			iconIcon = new IconSymbol(Color.blue.brighter());
		}
		return iconIcon;
	}

	public static Icon getThumbIcon()
	{
		if (thumbIcon == null)
		{
			thumbIcon = new ThumbIcon(false);
		}
		return thumbIcon;
	}

	public static Icon getThumbRolloverIcon()
	{
		if (thumbRolloverIcon == null)
		{
			thumbRolloverIcon = new ThumbIcon(true);
		}
		return thumbRolloverIcon;
	}

	public static Icon getRadioIcon()
	{
		if (radioIcon == null)
			radioIcon = new RadioButtonIcon();
		return radioIcon;
	}

	public static Icon getCheckIcon()
	{
		if (checkIcon == null)
			checkIcon = new CheckBoxIcon();
		return checkIcon;
	}

	public static LazyScaleIcon getScaleIcon(String name)
	{
		if (name != null)
			return new LazyScaleIcon(RIconFactory.class, name);
		return null;
	}

	public static class IconSymbol extends Symbol
	{
		public IconSymbol(Color iconColor)
		{
			super(iconColor);
		}

		public IconSymbol(Color iconColor, Dimension size)
		{
			super(iconColor, size);
		}

		public IconSymbol(Color iconColor, Component component)
		{
			super(iconColor, component);
		}

		public IconSymbol(Color iconColor, Color rolloverColor)
		{
			super(iconColor, rolloverColor);
		}

		public IconSymbol(Color iconColor, Color shadowColor,
				Color rolloverColor)
		{
			super(iconColor, shadowColor, rolloverColor);
		}

		@Override
		public void paint(Graphics2D g2d, int w, int h, Color color,
				Color shadowColor)
		{
			// int lw = (w / 12) + 1;
			int lw = (h > 22) ? 3 : 2;
			int dx = (w / 5) + 2;
			int dy = dx;

			g2d.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_MITER));
			if (shadowColor != null)
			{
				g2d.setColor(shadowColor);
				g2d.drawLine(dx + 1, h - dy, w - dx + 1, h - dy);
			}
			g2d.setColor(color);
			g2d.drawLine(dx, h - dy - 1, w - dx, h - dy - 1);
		}
	}

	public static class MaxSymbol extends Symbol
	{
		public MaxSymbol(Color iconColor)
		{
			super(iconColor);
		}

		public MaxSymbol(Color iconColor, Dimension size)
		{
			super(iconColor, size);
		}

		public MaxSymbol(Color iconColor, Component component)
		{
			super(iconColor, component);
		}

		public MaxSymbol(Color iconColor, Color rolloverColor)
		{
			super(iconColor, rolloverColor);
		}

		public MaxSymbol(Color iconColor, Color shadowColor,
				Color rolloverColor)
		{
			super(iconColor, shadowColor, rolloverColor);
		}

		@Override
		public void paint(Graphics2D g2d, int w, int h, Color color,
				Color shadowColor)
		{
			int lw = (h > 22) ? 2 : 1;
			int dx = (w / 5) + 1;
			int dy = (h / 5) + 2;

			g2d.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_MITER));
			if (shadowColor != null)
			{
				g2d.setColor(shadowColor);
				g2d.drawRect(dx + 1, dy + 1, w - (2 * dx), h - (2 * dy));
				g2d.drawLine(dx + 1, dy + lw + 1, w - dx, dy + lw + 1);
			}
			g2d.setColor(color);
			g2d.drawRect(dx, dy, w - (2 * dx), h - (2 * dy));
			g2d.drawLine(dx + 1, dy + lw, w - dx, dy + lw);
		}
	}

	public static class MinSymbol extends Symbol
	{
		public MinSymbol(Color iconColor)
		{
			super(iconColor);
		}

		public MinSymbol(Color iconColor, Dimension size)
		{
			super(iconColor, size);
		}

		public MinSymbol(Color iconColor, Component component)
		{
			super(iconColor, component);
		}

		public MinSymbol(Color iconColor, Color rolloverColor)
		{
			super(iconColor, rolloverColor);
		}

		public MinSymbol(Color iconColor, Color shadowColor,
				Color rolloverColor)
		{
			super(iconColor, shadowColor, rolloverColor);
		}

		private void paintRect(Graphics2D g2D, int x, int y, int w, int h,
				int lw, Color color, Color shadowColor)
		{
			if (shadowColor != null)
			{
				g2D.setColor(shadowColor);
				g2D.drawRect(x + 1, y + 1, w, h);
				g2D.drawLine(x + 1, y + lw + 1, x + w + 1, y + lw + 1);
			}
			g2D.setColor(color);
			g2D.drawRect(x, y, w, h);
			g2D.drawLine(x, y + lw, x + w, y + lw);
		}

		@Override
		public void paint(Graphics2D g2d, int w, int h, Color color,
				Color shadowColor)
		{
			int lw = (h > 22) ? 2 : 1;
			int delta = w / 4;
			w = Math.min(w, h) - 6;
			h = w;
			int x1 = 3;
			int y1 = 3;
			int w1 = w - delta;
			int h1 = h - delta;
			int x2 = delta + 2;
			int y2 = Math.max(delta + 2, y1 + (2 * lw) + 1);
			int w2 = w - delta;
			int h2 = h - delta;
			Shape savedClip = g2d.getClip();
			g2d.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_MITER));
			Area clipArea = new Area(savedClip);
			clipArea.subtract(new Area(new Rectangle2D.Double(x2, y2, w2, h2)));
			g2d.setClip(clipArea);
			paintRect(g2d, x1, y1, w1, h1, lw, color, shadowColor);
			g2d.setClip(savedClip);
			paintRect(g2d, x2, y2, w2, h2, lw, color, shadowColor);
		}
	}

	public static class CloseSymbol extends Symbol
	{
		public CloseSymbol(Color iconColor)
		{
			super(iconColor);
		}

		public CloseSymbol(Color iconColor, Dimension size)
		{
			super(iconColor, size);
		}

		public CloseSymbol(Color iconColor, Component component)
		{
			super(iconColor, component);
		}

		public CloseSymbol(Color iconColor, int width, int height)
		{
			super(iconColor, width, height);
		}

		public CloseSymbol(Color iconColor, Color rolloverColor)
		{
			super(iconColor, rolloverColor);
		}

		public CloseSymbol(Color iconColor, Color shadowColor,
				Color rolloverColor)
		{
			super(iconColor, shadowColor, rolloverColor);
		}

		@Override
		public void paint(Graphics2D g2d, int w, int h, Color color,
				Color shadowColor)
		{
			int d = w > h ? h : w;
			int lw = (d > 22) ? 3 : 2;
			int dl = d / 3;
			int dx = (w - dl) / 2;
			int dy = (h - dl) / 2;
			g2d.setStroke(new BasicStroke(lw, BasicStroke.CAP_ROUND,
					BasicStroke.JOIN_BEVEL));
			if (shadowColor != null)
			{
				g2d.setColor(shadowColor);
				g2d.drawLine(dx + 1, dy + 1, dx + dl + 1, dy + dl + 1);
				g2d.drawLine(dx + dl + 1, dy + 1, dx + 1, dy + dl + 1);
			}
			g2d.setColor(color);
			g2d.drawLine(dx, dy, dx + dl, dy + dl);
			g2d.drawLine(dx + dl, dy, dx, dy + dl);
		}
	}

	public static abstract class Symbol implements Icon
	{
		protected Color iconColor = null;
		protected Color shadowColor = null;
		protected Color rolloverColor = null;
		protected Dimension size = null;
		private Component component;
		private RenderingConfig renderingConfig = new RenderingConfig();

		public Symbol(Color iconColor)
		{
			this.iconColor = iconColor;
		}

		public Symbol(Color iconColor, Dimension size)
		{
			this.iconColor = iconColor;
			this.size = size;
		}

		public Symbol(Color iconColor, Component component)
		{
			this.iconColor = iconColor;
			this.component = component;
		}

		public Symbol(Color iconColor, int width, int height)
		{
			this.iconColor = iconColor;
			size = new Dimension(width, height);
		}

		public Symbol(Color iconColor, Color rolloverColor)
		{
			this.iconColor = iconColor;
			this.rolloverColor = rolloverColor;
		}

		public Symbol(Color iconColor, Color shadowColor, Color rolloverColor)
		{
			this.iconColor = iconColor;
			this.shadowColor = shadowColor;
			this.rolloverColor = rolloverColor;
		}

		public void setIconColor(Color iconColor)
		{
			this.iconColor = iconColor;
		}

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y)
		{
			// int ww = size != null ? size.width : c.getWidth();
			// int hh = size != null ? size.height : c.getHeight();
			int w = getIconWidth();
			int h = getIconHeight();

			Color color = iconColor;
			if (c instanceof AbstractButton && (rolloverColor != null))
				if (((AbstractButton) c).getModel().isRollover())
					color = rolloverColor;

			Graphics2D g2d = (Graphics2D) g;
			g2d.translate(x, y);
			Stroke savedStroke = g2d.getStroke();
			renderingConfig.setAAPainting(g2d);

			paint(g2d, w, h, color, shadowColor);

			g2d.translate(-x, -y);
			g2d.setStroke(savedStroke);
			renderingConfig.resetAAPainting(g2d);
		}

		abstract public void paint(Graphics2D g2d, int w, int h, Color color,
				Color shadowColor);

		@Override
		public int getIconHeight()
		{
			if (size != null)
				return size.height;
			if (component != null)
				return component.getHeight();
			return 17;
		}

		@Override
		public int getIconWidth()
		{
			if (size != null)
				return size.width;
			if (component != null)
				return component.getWidth();
			return 17;
		}
	}

	static class ThumbIcon implements Icon, UIResource, Serializable
	{
		private static final long serialVersionUID = -3268237792184108205L;
		private final static int width = 15;
		private final static int height = 15;
		private boolean isRollover;
		private RenderingConfig renderingConfig = new RenderingConfig();

		public ThumbIcon(boolean isRollover)
		{
			this.isRollover = isRollover;
		}

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y)
		{
			Graphics2D g2d = (Graphics2D) g;
			Color colors[];
			if (isRollover)
				colors = RThemeColor.getRolloverColors();
			else
				colors = RThemeColor.getDefaultColors();

			Shape savedClip = g2d.getClip();
			if (savedClip != null)
			{
				g2d.clip(new Ellipse2D.Double(x + 1, y + 1, width - 1,
						height - 1));
				GraphicsTools.fillHorGradient(g, colors, x + 1, y + 1, width,
						height);
			} else
			{
				g2d.setClip(new Ellipse2D.Double(x + 1, y + 1, width, height));
				GraphicsTools.fillHorGradient(g, colors, x, y, width, height);
			}
			g2d.setClip(savedClip);

			renderingConfig.setAAPainting(g2d);

			if (isRollover)
				g2d.setColor(RThemeColor.themeColor);
			else
				g2d.setColor(borderColor);
			g2d.drawOval(x + 1, y + 1, width - 1, height - 1);
			renderingConfig.resetAAPainting(g2d);
		}

		@Override
		public int getIconWidth()
		{
			return width + 2;
		}

		@Override
		public int getIconHeight()
		{
			return height + 2;
		}
	}

	public static class RadioButtonIcon
			implements
			Icon,
			UIResource,
			Serializable
	{
		private static final long serialVersionUID = -1717184594782767511L;
		public static final int oR = 14, dR = 6;
		public static final int GAP = 0;
		public static final Color blackColor = new Color(0, 0, 0, 200);
		public static final Color lightColor = new Color(220, 220, 220, 150);
		public static GradientPaint borderPaint = new GradientPaint(0, 0,
				lightColor, 0, oR, blackColor);
		public static Color lightTransColor = new Color(250, 250, 250, 180);
		public static Color rolloverLightColor = new Color(250, 250, 250, 220);
		RenderingConfig renderingConfig = new RenderingConfig();

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y)
		{
			//			if (!ComponentTools.isLeftToRight(c))
			//				x += GAP;
			double fx = x, fy = y + 0.5;
			Graphics2D g2d = (Graphics2D) g;
			g2d.translate(fx, fy);
			AbstractButton button = (AbstractButton) c;
			ButtonModel model = button.getModel();
			Color color;
			if ((button.isRolloverEnabled() && model.isRollover())
					|| (model.isPressed() && model.isArmed()))
			{
				color = rolloverLightColor;
			} else
			{
				color = lightTransColor;
			}
			renderingConfig.setAAPainting(g2d);

			g2d.setPaint(borderPaint);
			g.fillOval(0, 0, oR, oR);
			g.setColor(color);
			g.fillOval(1, 1, oR - 2, oR - 2);

			if (model.isSelected())
			{
				x = (oR - dR) / 2;
				y = (oR - dR) / 2;
				// g2d.setColor(RColorSet.blackBGColor);
				g2d.setColor(blackColor);
				g2d.fillOval(x, y, dR, dR);
			}
			renderingConfig.resetAAPainting(g2d);
			g2d.translate(-fx, -fy);
		}

		@Override
		public int getIconWidth()
		{
			return oR + GAP;
		}

		@Override
		public int getIconHeight()
		{
			return oR;
		}
	}

	static class CheckBoxIcon implements Icon, UIResource, Serializable
	{
		private static final long serialVersionUID = -3767329290986354723L;
		private static final int oR = 14;
		private static final int GAP = 0;
		static Color lightTransColor = new Color(230, 230, 230, 180);
		static Color rolloverLightColor = new Color(230, 230, 230, 220);
		RenderingConfig renderingConfig = new RenderingConfig();
		//		private static GradientPaint borderPaint = new GradientPaint(0, 0,
		//				RThemeColor.lightColor, 0, oR, RThemeColor.blackColor);

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y)
		{
			//			if (!ComponentTools.isLeftToRight(c))
			//				x += GAP;

			Graphics2D g2d = (Graphics2D) g;
			g2d.translate(x, y + 0.5);
			AbstractButton button = (AbstractButton) c;
			ButtonModel model = button.getModel();
			boolean isEnable = button.isEnabled();
			Composite composite = null;
			if (!isEnable)
			{
				composite = g2d.getComposite();
				g2d.setComposite(alphaComposite.derive(0.3f));
			}
			Color color;
			if (isEnable && button.isRolloverEnabled() && model.isRollover())
			{
				color = rolloverLightColor;
			} else
			{
				color = lightTransColor;
			}
			renderingConfig.setAAPainting(g2d);

			//			g2d.setPaint(borderPaint);
			//			g.fillRoundRect(1, 1, oR - 2, oR - 2, 3, 3);
			g.setColor(color);
			g.fillRoundRect(1, 1, oR - 2, oR - 2, 3, 3);
			g2d.setColor(borderColor);
			g.drawRoundRect(1, 1, oR - 2, oR - 2, 3, 3);

			if (model.isSelected())
			{
				g2d.setColor(RColorSet.blackBGColor);
				GraphicsTools.drawCheckmark(g2d);
			}
			renderingConfig.resetAAPainting(g2d);
			if (!isEnable)
				g2d.setComposite(composite);
			g2d.translate(-x, -y - 0.5);
		}

		@Override
		public int getIconWidth()
		{
			return oR + GAP;
		}

		@Override
		public int getIconHeight()
		{
			return oR;
		}
	}

	static abstract class RAbstractIcon implements Icon, UIResource
	{
		protected int width = 16;
		protected int height = 16;

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y)
		{
			Graphics2D g2d = (Graphics2D) g;
			g2d.translate(x, y);
			paintIcon(c, g2d);
			g2d.translate(-x, -y);
		}

		protected abstract void paintIcon(Component c, Graphics2D g2d);

		@Override
		public int getIconWidth()
		{
			return width;
		}

		@Override
		public int getIconHeight()
		{
			return height;
		}
	}

	public static class RFileChooserDetailsViewIcon extends RAbstractIcon
	{
		@Override
		protected void paintIcon(Component c, Graphics2D g)
		{
			g.setColor(RThemeColor.colorSet.textColor);
			g.fillRect(2, 3, 2, 2);
			g.fillRect(2, 7, 2, 2);
			g.fillRect(2, 11, 2, 2);
			g.fillRect(6, 3, 8, 2);
			g.fillRect(6, 7, 8, 2);
			g.fillRect(6, 11, 8, 2);
		}
	}
	public static class RFileChooserHomeFolderIcon extends RAbstractIcon
	{
		Shape shape;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.textColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape()
		{
			if (shape == null)
				shape = ShapeTools.createPath(2, 8, 8, 2, 14, 8, 12, 8, 12, 13,
						9, 13, 9, 10, 7, 10, 7, 13, 4, 13, 4, 8);
			return shape;
		}
	}
	public static class RFileChooserListViewIcon extends RAbstractIcon
	{
		@Override
		protected void paintIcon(Component c, Graphics2D g)
		{
			g.setColor(RThemeColor.colorSet.textColor);
			g.fillRect(3, 3, 4, 4);
			g.fillRect(3, 9, 4, 4);
			g.fillRect(9, 9, 4, 4);
			g.fillRect(9, 3, 4, 4);
		}
	}
	public static class RFileChooserNewFolderIcon extends RAbstractIcon
	{
		Shape shape1, shape2;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.textColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape1());
			g2d.fill(getShape2());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape1()
		{
			if (shape1 == null)
				shape1 = ShapeTools.createPath(2, 3, 5.5, 3, 7, 5, 14, 5, 14, 8,
						11, 8, 11, 10, 9, 10, 9, 13, 2, 13);
			return shape1;
		}
		public Shape getShape2()
		{
			if (shape2 == null)
				shape2 = ShapeTools.createPath(14, 11, 16, 11, 16, 13, 14, 13,
						14, 15, 12, 15, 12, 13, 10, 13, 10, 11, 12, 11, 12, 9,
						14, 9, 14, 11);
			return shape2;
		}
	}
	public static class RFileChooserUpFolderIcon extends RAbstractIcon
	{
		Shape shape1, shape2;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			renderingConfig.setAAPainting(g2d);
			g2d.setColor(RThemeColor.colorSet.textColor);
			g2d.fill(getShape1());
			g2d.fill(getShape2());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape1()
		{
			if (shape1 == null)
				shape1 = ShapeTools.createPath(2, 3, 5.5, 3, 7, 5, 9, 5, 9, 9,
						13, 9, 13, 5, 14, 5, 14, 13, 2, 13);
			return shape1;
		}
		public Shape getShape2()
		{
			if (shape2 == null)
				shape2 = ShapeTools.createPath(12, 4, 12, 8, 10, 8, 10, 4, 8, 4,
						11, 1, 14, 4, 12, 4);
			return shape2;
		}
	}
	public static class RFileViewComputerIcon extends RAbstractIcon
	{
		Path2D path;
		@Override
		protected void paintIcon(Component c, Graphics2D g)
		{
			g.setColor(RThemeColor.colorSet.textColor);
			g.fill(getPath());
			g.fillRect(2, 12, 12, 2);
		}
		public Path2D getPath()
		{
			if (path == null)
			{
				path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				path.append(new Rectangle2D.Float(2, 3, 12, 8), false);
				path.append(new Rectangle2D.Float(4, 5, 8, 4), false);
			}
			return path;
		}
	}
	public static class RFileViewDirectoryIcon extends RAbstractIcon
	{
		Shape shape;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.iconColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape()
		{
			if (shape == null)
				shape = ShapeTools.createPath(1, 2, 6, 2, 8, 4, 15, 4, 15, 13,
						1, 13);
			return shape;
		}
	}
	public static class RFileViewFileIcon extends RAbstractIcon
	{
		Shape shape1, shape2;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.iconColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape1());
			g2d.fill(getShape2());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape1()
		{
			if (shape1 == null)
				shape1 = ShapeTools.createPath(8, 6, 8, 1, 13, 1, 13, 15, 3, 15,
						3, 6);
			return shape1;
		}
		public Shape getShape2()
		{
			if (shape2 == null)
				shape2 = ShapeTools.createPath(3, 5, 7, 5, 7, 1);
			return shape2;
		}
	}
	public static class RFileViewFloppyDriveIcon extends RAbstractIcon
	{
		Path2D path;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.textColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getPath());
			g2d.fillRect(6, 12, 4, 2);
			renderingConfig.resetAAPainting(g2d);
		}

		public Path2D getPath()
		{
			if (path == null)
			{
				path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				Shape shape1 = ShapeTools.createPath(11, 14, 11, 11, 5, 11, 5,
						14, 2, 14, 2, 2, 14, 2, 14, 14, 11, 14);
				Shape shape2 = ShapeTools.createPath(4, 4, 4, 8, 12, 8, 12, 4,
						4, 4);
				path.append(shape1, false);
				path.append(shape2, false);
			}
			return path;
		}
	}
	public static class RFileViewHardDriveIcon extends RAbstractIcon
	{
		Path2D path;
		@Override
		protected void paintIcon(Component c, Graphics2D g)
		{
			g.setColor(RThemeColor.colorSet.textColor);
			g.fill(getPath());
		}
		public Path2D getPath()
		{
			if (path == null)
			{
				path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				path.append(new Rectangle2D.Float(2, 6, 12, 4), false);
				path.append(new Rectangle2D.Float(12, 8, 1, 1), false);
				path.append(new Rectangle2D.Float(10, 8, 1, 1), false);
			}
			return path;
		}
	}

	public static class RTreeClosedIcon extends RAbstractIcon
	{
		Shape shape;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.iconColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape()
		{
			if (shape == null)
				shape = ShapeTools.createPath(1, 2, 6, 2, 8, 4, 15, 4, 15, 13,
						1, 13);
			return shape;
		}
	}
	public static class RTreeCollapsedIcon extends RAbstractIcon
	{
		Shape shape;
		protected RenderingConfig renderingConfig = new RenderingConfig();
		public RTreeCollapsedIcon()
		{
			width = height = 11;
		}
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			rotate(c, g2d, 180);
			g2d.setColor(RThemeColor.colorSet.iconColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape());
			renderingConfig.resetAAPainting(g2d);
			rotate(c, g2d, -180);
		}
		public Shape getShape()
		{
			if (shape == null)
				shape = ShapeTools.createPath(2, 1, 2, 10, 10, 5.5);
			return shape;
		}
		protected void rotate(Component c, Graphics2D g, int angdeg)
		{
			if (!c.getComponentOrientation().isLeftToRight())
				g.rotate(Math.toRadians(angdeg), width / 2.0, height / 2.0);
		}
	}
	public static class RTreeExpandedIcon extends RTreeCollapsedIcon
	{
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			rotate(c, g2d, 90);
			g2d.setColor(RThemeColor.colorSet.iconColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape());
			renderingConfig.resetAAPainting(g2d);
			rotate(c, g2d, -90);
		}
	}

	public static class RTreeLeafIcon extends RAbstractIcon
	{
		Shape shape1, shape2;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.iconColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape1());
			g2d.fill(getShape2());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape1()
		{
			if (shape1 == null)
				shape1 = ShapeTools.createPath(8, 6, 8, 1, 13, 1, 13, 15, 3, 15,
						3, 6);
			return shape1;
		}
		public Shape getShape2()
		{
			if (shape2 == null)
				shape2 = ShapeTools.createPath(3, 5, 7, 5, 7, 1);
			return shape2;
		}
	}
	public static class RTreeOpenIcon extends RAbstractIcon
	{
		Shape shape1, shape2;
		RenderingConfig renderingConfig = new RenderingConfig();
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(RThemeColor.colorSet.iconColor);
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getShape1());
			g2d.fill(getShape2());
			renderingConfig.resetAAPainting(g2d);
		}
		public Shape getShape1()
		{
			if (shape1 == null)
				shape1 = ShapeTools.createPath(1, 2, 6, 2, 8, 4, 14, 4, 14, 6,
						3.5, 6, 1, 11);
			return shape1;
		}
		public Shape getShape2()
		{
			if (shape2 == null)
				shape2 = ShapeTools.createPath(4, 7, 16, 7, 13, 13, 1, 13);
			return shape2;
		}
	}

	static abstract class ROptionPaneAbstractIcon extends RAbstractIcon
	{
		protected Color lightColor, darkColor, blackColor;
		Path2D iconPath;
		RenderingConfig renderingConfig = new RenderingConfig();
		public ROptionPaneAbstractIcon()
		{
			width = height = 32;
		}
		@Override
		protected void paintIcon(Component c, Graphics2D g2d)
		{
			g2d.setColor(
					UITools.chooseColor(lightColor, darkColor, blackColor));
			renderingConfig.setAAPainting(g2d);
			g2d.fill(getIconPath());
			renderingConfig.resetAAPainting(g2d);
		}
		public Path2D getIconPath()
		{
			if (iconPath == null)
			{
				Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				path.append(createOutside(), false);
				path.append(createInside(), false);
				iconPath = path;
			}
			return iconPath;
		}
		protected abstract Shape createOutside();

		protected abstract Shape createInside();
	}

	public static class ROptionPaneErrorIcon extends ROptionPaneAbstractIcon
	{
		Shape shape1;
		Path2D shape2;
		public ROptionPaneErrorIcon()
		{
			lightColor = new Color(0xDB5860);
			darkColor = lightColor.brighter();
			blackColor = new Color(0xC75450);
		}

		@Override
		protected Shape createOutside()
		{
			if (shape1 == null)
				shape1 = new Ellipse2D.Float(2, 2, 28, 28);
			return shape1;
		}

		@Override
		protected Shape createInside()
		{
			if (shape2 == null)
			{
				shape2 = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				shape2.append(new Rectangle2D.Float(14, 7, 4, 11), false);
				shape2.append(new Rectangle2D.Float(14, 21, 4, 4), false);
			}
			return shape2;
		}
	}

	public static class ROptionPaneInformationIcon
			extends
			ROptionPaneAbstractIcon
	{
		Shape shape1;
		Path2D shape2;
		public ROptionPaneInformationIcon()
		{
			lightColor = new Color(0x389FD6);
			darkColor = lightColor.brighter();
			blackColor = new Color(0x3592C4);
		}

		@Override
		protected Shape createOutside()
		{
			if (shape1 == null)
				shape1 = new Ellipse2D.Float(2, 2, 28, 28);
			return shape1;
		}

		@Override
		protected Shape createInside()
		{
			if (shape2 == null)
			{
				shape2 = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				shape2.append(new Rectangle2D.Float(14, 14, 4, 11), false);
				shape2.append(new Rectangle2D.Float(14, 7, 4, 4), false);
			}
			return shape2;
		}
	}

	public static class ROptionPaneQuestionIcon extends ROptionPaneAbstractIcon
	{
		Shape shape1;
		Path2D shape2;
		public ROptionPaneQuestionIcon()
		{
			lightColor = new Color(0x389FD6);
			darkColor = lightColor.brighter();
			blackColor = new Color(0x3592C4);
		}

		@Override
		protected Shape createOutside()
		{
			if (shape1 == null)
				shape1 = new Ellipse2D.Float(2, 2, 28, 28);
			return shape1;
		}

		@Override
		protected Shape createInside()
		{
			if (shape2 == null)
			{
				Path2D q = new Path2D.Float();
				q.moveTo(14, 20);
				q.lineTo(18, 20);
				q.curveTo(18, 16, 23, 16, 23, 12);
				q.curveTo(23, 8, 20, 6, 16, 6);
				q.curveTo(12, 6, 9, 8, 9, 12);
				q.curveTo(9, 12, 13, 12, 13, 12);
				q.curveTo(13, 10, 14, 9, 16, 9);
				q.curveTo(18, 9, 19, 10, 19, 12);
				q.curveTo(19, 15, 14, 15, 14, 20);
				q.closePath();
				shape2 = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				shape2.append(new Rectangle2D.Float(14, 22, 4, 4), false);
				shape2.append(q, false);
			}
			return shape2;
		}
	}

	public static class ROptionPaneWarningIcon extends ROptionPaneAbstractIcon
	{
		Shape shape1;
		Path2D shape2;
		public ROptionPaneWarningIcon()
		{
			lightColor = new Color(0xEDA200);
			darkColor = lightColor.brighter();
			blackColor = new Color(0xF0A732);
		}

		@Override
		protected Shape createOutside()
		{
			if (shape1 == null)
				shape1 = ShapeTools.createPath(16, 2, 31, 28, 1, 28);
			return shape1;
		}

		@Override
		protected Shape createInside()
		{
			if (shape2 == null)
			{
				shape2 = new Path2D.Float(Path2D.WIND_EVEN_ODD);
				shape2.append(new Rectangle2D.Float(14, 10, 4, 8), false);
				shape2.append(new Rectangle2D.Float(14, 21, 4, 4), false);
			}
			return shape2;
		}
	}
}
